<template>
  <div class="p-6 space-y-6">
    <h1 class="text-2xl font-bold">用户行为分析系统（动态 Sankey）</h1>

    <div>
      <h2 class="text-xl font-semibold mb-2">用户行为路径图（Sankey）</h2>
      <div class="chart-wrapper" ref="sankeyChartRef" style="height: 500px; width: 100%;"></div>
    </div>

    <div>
      <h2 class="text-xl font-semibold mb-2">栏目访问时长统计（秒）</h2>
      <div class="chart-wrapper" ref="barChartRef" style="height: 400px; width: 100%;"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import * as echarts from 'echarts/core'
import { SankeyChart, BarChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, GridComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'

echarts.use([SankeyChart, BarChart, TitleComponent, TooltipComponent, GridComponent, CanvasRenderer])

const sankeyChartRef = ref<HTMLDivElement | null>(null)
const barChartRef = ref<HTMLDivElement | null>(null)
let sankeyInstance: echarts.ECharts | null = null
let barInstance: echarts.ECharts | null = null

// 初始 Sankey 数据
const sankeyData = {
  nodes: [
    { name: '首页' },
    { name: '平台产品' },
    { name: '开源产品' },
    { name: '行业产品' },
    { name: '公司动态' },
    { name: '行业动态' },
    { name: '文章详情' },
    { name: '视频播放' },
    { name: '文件下载' },
  ],
  links: [
    { source: '首页', target: '平台产品', value: 10 },
    { source: '首页', target: '开源产品', value: 6 },
    { source: '首页', target: '行业产品', value: 6 },
    { source: '首页', target: '公司动态', value: 6 },
    { source: '首页', target: '行业动态', value: 6 },

    // 删除所有“未操作”相关链接，只保留正常流转
    { source: '平台产品', target: '文章详情', value: 7 },
    { source: '开源产品', target: '文章详情', value: 4 },
    { source: '行业产品', target: '文章详情', value: 4 },
    { source: '公司动态', target: '文章详情', value: 4 },
    { source: '行业动态', target: '文章详情', value: 4 },

    { source: '文章详情', target: '视频播放', value: 5 },
    { source: '文章详情', target: '文件下载', value: 3 },
  ],
}


// 访问时长数据
const visitDurations = ref<Record<string, number>>({
  首页: 0,
  平台产品: 0,
  开源产品: 0,
  行业产品: 0,
  公司动态: 0,
  行业动态: 0,
  文章详情: 0,
  视频播放: 0,
  文件下载: 0,
})

// 定时器引用
let timer: number | undefined

// 同步访问时长：根据 Sankey 各节点的流量动态更新访问时长
function syncVisitDurations() {
  // 先初始化所有访问时长为0
  Object.keys(visitDurations.value).forEach(key => {
    visitDurations.value[key] = 0
  })

  // 统计所有流量中，作为source的节点的value累计，作为访问时长依据
  // 这里的设计是根据节点进入和出去的流量来估算访问时长（单位模拟）

  // 遍历所有节点
  sankeyData.nodes.forEach(node => {
    const nodeName = node.name
    // 计算该节点所有进入流量总和
    const inLinks = sankeyData.links.filter(l => l.target === nodeName)
    const inSum = inLinks.reduce((sum, l) => sum + l.value, 0)

    // 计算该节点所有出去流量总和
    const outLinks = sankeyData.links.filter(l => l.source === nodeName)
    const outSum = outLinks.reduce((sum, l) => sum + l.value, 0)

    // 访问时长估计：节点流量的最大值加上一个基础数值（防止为0）
    // 你也可以调整这个逻辑，比如用 inSum 或者 outSum 或两者平均
    visitDurations.value[nodeName] = Math.max(inSum, outSum, 1)
  })
}

function updateSankeyChart() {
  if (!sankeyInstance) return
  sankeyInstance.setOption({
    backgroundColor: '#f5f5f5',
    tooltip: {
      trigger: 'item',
      formatter: (params: any) =>
          params.dataType === 'edge'
              ? `${params.data.source} → ${params.data.target}: ${params.data.value}`
              : params.data.name,
    },
    series: [
      {
        type: 'sankey',
        layout: 'none',
        emphasis: { focus: 'adjacency' },
        data: sankeyData.nodes,
        links: sankeyData.links,
        lineStyle: {
          color: 'gradient',
          curveness: 0.5,
        },
        label: {
          fontSize: 14,
          color: '#333',
        },
        itemStyle: {
          borderColor: '#aaa',
          borderWidth: 1,
        },
      },
    ],
  })
}

function updateBarChart() {
  if (!barInstance) return
  barInstance.setOption({
    backgroundColor: '#f5f5f5',
    title: { text: '栏目访问时长（秒）', left: 'center' },
    tooltip: {},
    xAxis: {
      type: 'category',
      data: Object.keys(visitDurations.value),
      axisLabel: {
        rotate: 45,          // 旋转45度，避免标签重叠
        interval: 0,         // 保证每个标签都显示
        fontSize: 12,
        formatter: (value: string) => value.length > 6 ? value.slice(0, 6) + '...' : value // 过长截断显示
      },
    },
    yAxis: {
      type: 'value',
      name: '秒',
    },
    series: [
      {
        data: Object.values(visitDurations.value),
        type: 'bar',
        color: '#73C0DE',
      },
    ],
  })
}

onMounted(async () => {
  syncVisitDurations()
  updateBarChart()
  await nextTick()

  if (sankeyChartRef.value) {
    sankeyInstance = echarts.init(sankeyChartRef.value)
    updateSankeyChart()
  }

  if (barChartRef.value) {
    barInstance = echarts.init(barChartRef.value)
    updateBarChart()
  }

  // 定时模拟数据变动，并同步访问时长
  timer = window.setInterval(() => {
    // 首页出链波动
    const rootLinks = sankeyData.links.filter(link => link.source === '首页')
    rootLinks.forEach(link => {
      const fluctuation = (Math.random() - 0.5) * 4
      let newValue = link.value + fluctuation
      if (newValue < 1) newValue = 1
      link.value = Math.round(newValue)
    })

    // 对其他节点的流量进行简单波动调整（去掉“未操作”分配）
    const updateLayer = (sources: string[]) => {
      sources.forEach(source => {
        const outLinks = sankeyData.links.filter(link => link.source === source)
        if (outLinks.length === 0) return

        const inLinks = sankeyData.links.filter(link => link.target === source)
        const inSum = inLinks.reduce((sum, l) => sum + l.value, 0)
        if (inSum === 0) return

        const normalSumCurrent = outLinks.reduce((sum, l) => sum + l.value, 0)
        const ratio = inSum / normalSumCurrent

        outLinks.forEach(link => {
          link.value = Math.max(1, Math.round(link.value * ratio))
        })
      })
    }

    updateLayer(['平台产品', '开源产品', '行业产品', '公司动态', '行业动态'])
    updateLayer(['文章详情'])

    updateSankeyChart()

    // 同步访问时长数据
    syncVisitDurations()
    updateBarChart()
  }, 300000)
})

onUnmounted(() => {
  if (timer) clearInterval(timer)
  sankeyInstance?.dispose()
  barInstance?.dispose()
})
</script>

<style scoped>
.chart-wrapper {
  background-color: #f5f5f5;
  border-radius: 8px;
  padding: 16px;
  box-sizing: border-box;
}
</style>
